package controller;

import model.AIPlayer;
import model.GamePiece;
import model.HumanPlayer;
import model.LadderGame;
import model.LadderGameListener;
import model.LadderGridHelper;
import model.Player;
import view.GameViewer;

import java.io.*;
import java.util.ArrayList;

/**
 * This class invokes the player configuration menu.
 * It also initializes the LadderGame class to begin a new game.
 * 
 *
 */
public class Controller implements LadderGameListener
{
    private Player blackPlayer;
    private Player whitePlayer;

    public LadderGame game;

    public Controller()
    {
    	GameViewer.printWelcomeMessage();
    	playerSelect();
        this.game = new LadderGame(this);
        
    }

    public void newGame() throws Exception
    {
        this.game.NewGame(blackPlayer, whitePlayer);
    }

    @Override
    public void onNewGame()
    {
        GameViewer.printNewGameMessage();
        GameViewer.display(game.getGrid());
        this.insertNextPiece();
    }

    @Override
    public void onIllegalMove(String position, Player player)
    {
        System.out.println("Error : move " + position + " is illegal");
        this.insertNextPiece();
    }

    @Override
    public void onErrorOccured(String message)
    {
        System.out.println("Error : " + message);
        this.insertNextPiece();
    }

    @Override
    public void onPlayerWins(Player player)
    {
        GameViewer.display(game.getGrid());
        GameViewer.printPlayerWinsMessage(player);
    }

    @Override
    public void onTie()
    {
        GameViewer.display(game.getGrid());
        GameViewer.printTieMessage();
    }

    @Override
    public void onPlayerTurnFinished(Player player, String move)
    {
        try
        {
            GameViewer.printPlayerTurnEndsMessage(player, move);
            GameViewer.display(game.getGrid());            
            this.game.getOpponentPlayer(player).OnOpponentPlayedMove(move);            
            this.insertNextPiece();
        }
        catch (Exception e)
        {
            System.out.println("ERROR ! : " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * Makes the next player to play play his move.
     */
    private void insertNextPiece()
    {
        try
        {
            Player currentPlayer = this.game.getCurrentPlayer();
            ArrayList<ArrayList<GamePiece>> gridCopy = LadderGridHelper.deepCopy(this.game.getGrid());
            
            String nextMove = currentPlayer.getNextMove(gridCopy, this.game.getGamePieceForPlayer(currentPlayer));
            
            if (nextMove == null)
            {
                throw new Exception("Player " + currentPlayer.getName() + " does not know what to do !");
            }
            else if(nextMove.toLowerCase().equals("reset")){
            	Controller controllerNew = new Controller();
                controllerNew.newGame();
                System.gc();
            }
            else if(nextMove.toLowerCase().equals("exit")){
            	GameViewer.printStopMessage();
            	System.exit(1);
            }
            else
            {
                this.game.insertPiece(nextMove);
            }
        }
        catch (Exception e)
        {
            System.out.println("ERROR ! : " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    public void playerSelect(){
    	
    	int flag = 0, id = 0;    	
        
    	do{
        	try{
        		id = Integer.parseInt(GameViewer.printPlayerSelect());
        		flag=0;
        	}catch(NumberFormatException e){
        		flag=1;
        	}
        	if(flag==0){
        		switch(id){
        			case 1:
        				this.blackPlayer = new AIPlayer("Black AI");
        				this.whitePlayer = new AIPlayer("White AI");
        				break;
        	
        			case 2:
        				this.blackPlayer = new HumanPlayer("Black");
        				this.whitePlayer = new AIPlayer("White AI");
        				break;
        	
        			case 3:
        				this.blackPlayer = new AIPlayer("Black AI");
        				this.whitePlayer = new HumanPlayer("White");
        				break;
        	
        			case 4:
        				this.blackPlayer = new HumanPlayer("Black");
        				this.whitePlayer = new HumanPlayer("White");
        				break;
        	
        			case 5: 
        				System.exit(1);
        	
        			default: 
        				flag=1;
        		}
        	}
        }while(flag == 1);    	
    }
}
